package com.leesche.netdoll.communication.protocol.decoder;

import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.leesche.framework.core.configuration.ConfigurationUtil;
import com.leesche.framework.core.json.GsonUtil;
import com.leesche.framework.core.lang.StringUtil;
import com.leesche.framework.core.lang.UncheckedException;

public class ResolverManager {

	private static final Logger logger = LogManager.getLogger(ResolverManager.class);

	private final Map<String, Resolver<?>> resolvers = new HashMap<>();

	private volatile static ResolverManager instance;

	private ResolverManager() {
		initResolver();
	}

	private void initResolver() {
		logger.info("initializing message resolvers...");

		Map<String, String> resolverConfs = GsonUtil.toMap(ConfigurationUtil.locateFromClasspath("resolver.json"), String.class, String.class);

		if (resolverConfs != null && resolverConfs.size() > 0) {
			for (String key : resolverConfs.keySet()) {
				String clazz = resolverConfs.get(key);

				if (StringUtil.isNotBlank(clazz)) {
					try {
						resolvers.put(key, (Resolver<?>) Class.forName(clazz).newInstance());

						logger.info("Resolver {} is initialized with '{}'.", key, clazz);

					} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
						throw new UncheckedException("failed to create resolver for \"{0}\".", e, clazz);
					}
				}
			}
		}

		logger.info("initializing message resolvers...OK");

	}

	public static ResolverManager newInstance() {
		if (instance == null) {
			synchronized (ResolverManager.class) {
				if (instance == null)
					instance = new ResolverManager();
			}
		}
		return instance;
	}

	public Resolver<?> resolver(String name) throws ResolverNotFountException {
		if (!resolvers.containsKey(name)) {
			logger.info("try to get an non-exist resolver with id '{}'.", name);
			return null;
		}

		return resolvers.get(name);
	}
}
